Getting Started
Getting started to easily add ERC-4337 smart wallet support to your application.
Once setup, your application will:
- Let users connect to their smart wallet using any personal wallet, including email and local wallets for easy onboarding.
- Automatically deploy individual account contracts for your users when they do their first onchain transaction.
- Handle all transaction gas costs via the thirdweb paymaster.
1. Smart Wallet Factory Contract
Deployable via the explore page or build your own ERC 4337 compatible factory contract using the Solidity SDK.
Choose the right smart wallet setup for your app. thirdweb offers the following three different kinds of smart wallets:
Account setup | DynamicAccount setup | ManagedAccount setup | |
---|---|---|---|
Upgradeability | Non-upgradeable | Account upgrades controlled locally by account admin. | Account upgrades controlled centrally by account factory admin. |
User persona | Developer wants to issue simple smart wallets to their users. They do not anticipate that users wallets will need any feature upgrades. | Developer wants to issue smart wallets to their users. They do anticipate feature upgrades to user wallets but do not want to push upgrades to user wallets without consent. | Developer wants to issue smart wallets to their users. They do anticipate feature upgrades to user wallets, and want to push upgrades to user wallets for seamless/invisible UX for upgrades. |
Supported chains
View supported chains
- Polygon
- Optimism
- Base
- Arbitrum
- Linea
- Goerli
- Sepolia
- Mumbai
- Base Goerli
- Optimism Goerli
- Arbitrum Goerli
- Linea Testnet
- Celo Alfajores Testnet
To support a chain not listed, contact us.
2. An API key
You will require an API key to use thirdweb's infrastructure services such as the bundler and paymaster.
Obtain an API key from the thirdweb dashboard Settings page.
The API key lets you access thirdweb's bundler and paymaster infrastructure, which is required for the smart wallet to operate and optionally enable gasless transactions.
The API key will need to have the following settings:
- smart wallet as an enabled service
- The contracts that the smart wallet will interact with must be added to the "Destination Contracts" list. Learn more here
Learn more about creating an API key and restricting which contracts the smart wallet can interact with here.
3. Connecting & Creating Smart Wallets in an Application
Use the following code to integrate smart wallets into your apps. This will handle:
- Connecting your users to their smart wallet based of their personal wallet (can be any wallet, including email or local wallets).
- Automatically deploy the individual account contracts for your users when they do their first onchain transaction.
- Handle all transaction gas costs via the thirdweb paymaster.
- Select your deployed account factory and client ID to get a fully functional code snippet.
- TypeScript
- React
- React Native
- Unity
import { LocalWallet, SmartWallet } from "@thirdweb-dev/wallets";
// First, connect the personal wallet, which can be any wallet (metamask, walletconnect, etc.)
// Here we're just generating a new local wallet which can be saved later
const personalWallet = new LocalWallet();
await personalWallet.generate();
// Setup the Smart Wallet configuration
const config = {
chain: "goerli", // the chain where your smart wallet will be or is deployed
factoryAddress: "0x...", // your own deployed account factory address
clientId: "YOUR_CLIENT_ID", // or use secretKey for backend/node scripts
gasless: true, // enable or disable gasless transactions
};
// Then, connect the Smart wallet
const wallet = new SmartWallet(config);
await wallet.connect({
personalWallet,
});
import { ThirdwebProvider, ConnectWallet, smartWallet } from "@thirdweb-dev/react";
export default function App() {
return (
<ThirdwebProvider
clientId="YOUR_CLIENT_ID"
activeChain="goerli"
supportedWallets={[
smartWallet({
factoryAddress: "0x...",
gasless: true,
personalWallets={[...]}
})
]}
>
<ConnectWallet />
</ThirdwebProvider>
);
}
import { ThirdwebProvider, ConnectWallet, smartWallet } from "@thirdweb-dev/react-native";
export default function App() {
return (
<ThirdwebProvider
clientId="YOUR_CLIENT_ID"
activeChain="goerli"
supportedWallets={[
smartWallet({
factoryAddress: "0x...",
gasless: true,
personalWallets={[...]}
})
]}
>
<ConnectWallet />
</ThirdwebProvider>
);
}
using Thirdweb;
public async void ConnectWallet()
{
// Reference to your Thirdweb SDK
var sdk = ThirdwebManager.Instance.SDK;
// Configure the connection
var connection = new WalletConnection(
provider: WalletProvider.SmartWallet, // The wallet provider you want to connect to (Required)
chainId: 1, // The chain you want to connect to (Required)
password: "myEpicPassword", // If using a local wallet as personal wallet (Optional)
email: "email@email.com", // If using an email wallet as personal wallet (Optional)
personalWallet: WalletProvider.LocalWallet // The personal wallet you want to use with your Smart Wallet (Optional)
);
// Connect the wallet
string address = await sdk.wallet.Connect(connection);
}
Using a Template
Clone these templates to quickly deploy Smart Wallets and connect to them.
4. Executing gas free transactions with Smart Wallets
Once setup, you can use the thirdweb TypeScript, React, React Native and Unity SDKs to deploy contracts, perform transactions, and manipulate wallets just like you would with any other wallet.
- TypeScript
- React
- React Native
- Unity
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
// Simply initialize your SDK with the created smart wallet
const sdk = await ThirdwebSDK.fromWallet(smartWallet, "goerli", {
clientId: "YOUR_CLIENT_ID"
});
// You can now interact with the blockchain as you would with a regular EOA
const smartWalletAddress = await sdk.wallet.getAddress();
// gas free wallet actions
await sdk.wallet.transfer("0x...", "0.01");
// gas free contract deployments
const contractAddress = await sdk.deployer.deployNFTCollection({
name: "My NFT Collection",
primary_sale_recipient: smartWalletAddress
});
// gas free contract interactions
const contract = await sdk.getContract(contractAddress);
await contract.erc721.mint({
name: "My NFT",
description: "My NFT description",
image: "https://example.com/image.png",
});
import { useAddress, useContract, useOwnedNFTs, Web3Button } from "@thirdweb-dev/react";
// The ThirdwebProvider setup above already handles connection to the smart wallet
// Within the provider, you can use the react SDK hooks to interact with the blockchain
export default function MyComponent() {
// Get the connected smart wallet address
const smartWalletAddress = useAddress();
// Fetch owned NFTs
const { contract } = useContract("0x...");
const { data, isLoading } = useOwnedNFTs(contract, smartWalletAddress);
// Mint a new NFT
return (
<Web3Button
contractAddress={"0x..."}
action={(contract) => contract.erc721.mint({
name: "My NFT",
description: "My NFT description",
image: "https://example.com/image.png",
})
}
>
Mint NFT
</Web3Button>
);
}
import { useAddress, useContract, useOwnedNFTs, Web3Button } from "@thirdweb-dev/react-native";
// The ThirdwebProvider setup above already handles connection to the smart wallet
// Within the provider, you can use the react SDK hooks to interact with the blockchain
export default function MyComponent() {
// Get the connected smart wallet address
const smartWalletAddress = useAddress();
// Fetch owned NFTs
const { contract } = useContract("0x...");
const { data, isLoading } = useOwnedNFTs(contract, smartWalletAddress);
// Mint a new NFT
return (
<Web3Button
contractAddress={"0x..."}
action={(contract) => contract.erc721.mint({
name: "My NFT",
description: "My NFT description",
image: "https://example.com/image.png",
})
}
>
Mint NFT
</Web3Button>
);
}
using Thirdweb;
public async void MintNFT()
{
// The ThirdwebManger prefab holds the smart wallet connection state
var sdk = ThirdwebManager.Instance.SDK;
// Get the connected smart wallet address
var smartWalletAddress = await sdk.Wallet.GetAddress();
// Interact with contracts
Contract contract = sdk.GetContract("0x...");
await contract.ERC721.Mint(new NFTMetadata()
{
name = "My NFT",
description = "My NFT description",
image = "https://example.com/image.png",
});
}